// Copyright (c) 2011, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

part of dart.core;

/**
 * key-value键值对（可以使用相关联的key检索value值）的集合。
 *
 * Map中key的数量是有限的，每个key正好有一个相关的value。
 *
 * Map、以及它的键和值，都是可以迭代的。
 * 迭代的顺序由Map不同的类型定义。例如：
 *
 * * [HashMap]是无序的，这意味着它迭代的顺序是不确定的
 * * [LinkedHashMap]按key的插入顺序进行迭代
 * * [SplayTreeMap]按key的排序顺序进行迭代
 *
 * 当Map的一个操作正在执行的时候，通常不允许修改Map（添加或删除key），
 * 例如，在调用[forEach]或[putIfAbsent]期间。
 * 在迭代key或value时修改Map也可能会破坏迭代。
 */
abstract class Map<K, V> {
  /**
   * 创建一个Map实例，默认实现是[LinkedHashMap]。
   *
   * 该构造函数等同于非const的Map `<K,V>{}`。
   *
   * `LinkedHashMap`要求key实现`operator==`和`hashCode`，并且它允许`null`作为key。
   * 迭代顺序和key的插入顺序相同。
   */
  external factory Map();

  /**
   * 创建一个[LinkedHashMap]实例，包含[other]的所有键值对。
   *
   * key必须可以对[K]赋值，而value必须可以对[V]赋值。
   * [other]可能是Map的任何类型。
   *
   * `LinkedHashMap`要求key实现`operator==`和`hashCode`，并且它允许`null`作为key。
   * 迭代顺序和key的插入顺序相同。
   */
  factory Map.from(Map other) = LinkedHashMap<K, V>.from;

  /**
   * 创建一个不可修改、基于哈希值的Map，包含[other]所有的项。
   *
   * key必须可以对[K]赋值，而value必须可以对[V]赋值。
   * [other]可能是Map的任何类型。
   *
   * Map要求key实现`operator==`和`hashCode`，并且它允许`null`作为key。
   * 创建的Map迭代顺序是固定的，它保存了[other]的顺序。
   *
   * 它的行为表现和[Map.from]创建的Map一样，
   * 除了通过此构造函数返回的Map是不可修改的这点。
   */
  external factory Map.unmodifiable(Map other);

  /**
   * 使用默认实现[LinkedHashMap]创建一个严格的Map。
   *
   * 返回的Map允许`null`作为key，并且迭代顺序和key的插入顺序相同。
   */
  factory Map.identity() = LinkedHashMap<K, V>.identity;

  /**
   * 创建一个Map实例，其中Key和Value由[iterable]的元素计算得到。
   *
   *
   * 创建的Map是一个[LinkedHashMap]。
   * `LinkedHashMap`要求key实现`operator==`和`hashCode`，并且它允许`null`作为key。
   * 迭代顺序和key的插入顺序相同。
   *
   * 此构造函数通过分别应用[key]和[value]方法，使用[iterable]的每个元素作为参数来计算键值对。
   *
   * 下面的例子是根据一个List，创建一个新的Map。
   * `map`的key是由`list`值转换的字符串，
   * `map`的value则是`list`值的平方：
   *
   *     List<int> list = [1, 2, 3];
   *     Map<String, int> map = new Map.fromIterable(list,
   *         key: (item) => item.toString(),
   *         value: (item) => item * item);
   *
   *     map['1'] + map['2']; // 1 + 4
   *     map['3'] - map['2']; // 9 - 4
   *
   * 如果没有设置参数[key]和[value]，默认使用恒等函数`(x) => x`。
   *
   * 下面的例子中，key和`map`对应的value，都是`list`的值：
   *
   *     map = new Map.fromIterable(list);
   *     map[1] + map[2]; // 1 + 2
   *     map[3] - map[2]; // 3 - 2
   *
   * 通过[iterable]计算的key并不需要是唯一值，因为后面出现的key会覆盖之前的value。
   */
  factory Map.fromIterable(Iterable iterable,
      {K key(element), V value(element)}) = LinkedHashMap<K, V>.fromIterable;

  /**
   * 将指定的[keys]和[values]关联，创建一个Map实例。
   *
   * 创建的Map是一个[LinkedHashMap]。
   * [LinkedHashMap]要求keys实现`operator==`和`hashCode`方法，并且它允许null作为key。
   * [LinkedHashMap]按key的插入顺序进行迭代。
   *
   * 此构造函数会迭代[keys]和[values]，并且映射[keys]的每个元素到对应的[values]的元素。
   *
   *     List<String> letters = ['b', 'c'];
   *     List<String> words = ['bad', 'cat'];
   *     Map<String, String> map = new Map.fromIterables(letters, words);
   *     map['b'] + map['c'];  // badcat
   *
   * 如果[keys]包含相同的对象多次，最后出现的值会覆盖之前的值。
   *
   * 两个可迭代对象[Iterable]必须长度相同。
   */
  factory Map.fromIterables(Iterable<K> keys, Iterable<V> values)
      = LinkedHashMap<K, V>.fromIterables;

  /**
   * 如果`this`包含指定的[value]，返回true。
   *
   * 如果Map中的任何一个value根据`==`运算操作，等于`value`，则返回true。
   */
  bool containsValue(Object value);

  /**
   * 如果`this`包含指定的[key]，返回true。
   *
   * 如果Map中的任何一个key根据`==`运算操作，等于`key`，则返回true。
   */
  bool containsKey(Object key);

  /**
   * 通过指定的[key]，返回对应的value。如果Map中不存在[key]，返回null。
   *
   * 部分Map允许`null`作为value，
   * 对于那些Map，通过此运算符进行查找的时候，
   * 并不能区分是Map不存在key，还是key对应的值为null。
   * 如果区分操作很重要，可以使用[containsKey]或[putIfAbsent]方法。
   */
  V operator [](Object key);

  /**
   * 将指定的[value]与[key]相关联。
   *
   * 如果key已经存在于Map中，它关联的值会被更改。否则，key-value键值对被添加到Map中。
   */
  void operator []=(K key, V value);

  /**
   * 查找[key]对应的value，或添加一个新的value。
   *
   * 如果存在值，返回[key]关联的value。
   * 否则，调用[ifAbsent]，得到一个新的value，并且将值与[key]关联，返回新的value。
   *
   *     Map<String, int> scores = {'Bob': 36};
   *     for (var key in ['Bob', 'Rohan', 'Sophena']) {
   *       scores.putIfAbsent(key, () => key.length);
   *     }
   *     scores['Bob'];      // 36
   *     scores['Rohan'];    //  5
   *     scores['Sophena'];  //  7
   *
   * 调用[ifAbsent]的时候，不能进行添加或删除key的操作。
   */
  V putIfAbsent(K key, V ifAbsent());

  /**
   * 将[other]中所有的key-value键值对添加到`this`中。
   *
   * 如果[other]的某个key已经存在于`this`，它的值会被重写。
   *
   * 该操作等同于对`other`中每个key和关联的value，进行`this[key] = value`操作。
   * 它会迭代[other]，因此在迭代期间不能进行更改操作。
   */
  void addAll(Map<K, V> other);

  /**
   * 如果存在的话，从Map中删除[key]和它关联的value。
   *
   * 返回`key`被删除前关联的value。如果`key`不存在于Map中，返回`null`。
   *
   * 请注意，如果值可以为`null`，那么返回`null`并不总是意味着`key`不存在。
   */
  V remove(Object key);

  /**
   * 删除Map中所有的键值对。
   *
   * 在执行此操作之后，Map为空。
   */
  void clear();

  /**
   * 将[f]应用于Map的每个key-value键值对。
   *
   * 调用`f`的时候，Map不能添加或删除key。
   */
  void forEach(void f(K key, V value));

  /**
   * [this]的所有key。
   *
   * 返回的可迭代对象具有有效的`length`和`contains`操作，
   * 它基于Map的[length]和[containsKey]方法。
   *
   * 迭代的顺序是由不同的`Map`单独实现的，但是对于Map的更改一定是保持一致的。
   */
  Iterable<K> get keys;

  /**
   * [this]的所有value。
   *
   * value迭代的顺序是由对应的key的顺序确定的。
   * 也就是说，它将迭代[keys]和[values]，并同时提供所有键值对的匹配。
   *
   * 返回的可迭代对象具有有效的`length`方法，它基于Map的[length]。
   * 它的[Iterable.contains]方法基于`==`比较操作。
   */
  Iterable<V> get values;

  /**
   * Map中key-value键值对的数量。
   */
  int get length;

  /**
   * 如果Map中不存在key-value键值对，返回true。
   */
  bool get isEmpty;

  /**
   * 如果Map中至少有一个key-value键值对，返回true。
   */
  bool get isNotEmpty;
}
